// file: include/os/mutexlock.h
// autor: jiangxinpeng
// time: 2021.2.4
// copyright: (C) 2020-2050 by jiangxinpeng,All right are reserved.

#ifndef OS_MUTEXLOCK_H
#define OS_MUTEXLOCK_H

#include <os/spinlock.h>
#include <lib/list.h>

typedef struct mutexlock
{
    atomic_t wait_lock;
    list_t wait_list;
    int waiter;
} mutexlock_t;

// if is faild, task into sleepping
#define MUTEX_LOCK_MODE_BLOCK 0
// if is faild,return error
#define MUTEX_LOCK_MODE_ERROR 1
// if is faild,waitting unit succeed unlock
#define MUTEX_LOCK_MODE_WAITTING 2

#define MUTEX_LOCK_INIT(lockname)                                                                   \
    {                                                                                               \
        .wait_lock = ATOMIC_INIT(0), .wait_list = LIST_HEAD_INIT((lockname).wait_list), .waiter = 0 \
    }

#define DEFINE_MUTEX_LOCK(lockname) \
    mutexlock_t lockname = MUTEX_LOCK_INIT(lockname)

static inline void MutexlockInit(mutexlock_t *mutexlock)
{
    AtomicSet(&mutexlock->wait_lock, 0);
    list_init(&mutexlock->wait_list);
    mutexlock->waiter = 0;
}

static inline int MutexlockIsLock(mutexlock_t *mutexlock)
{
    return AtomicGet(&mutexlock->wait_lock);
}

static inline int MutexlockIsUnLock(mutexlock_t *mutexlock)
{
    return !AtomicGet(&mutexlock->wait_lock);
}

static inline int MutexlockTryLock(mutexlock_t *mutexlock)
{
    return AtomicXCHG(&mutexlock->wait_lock, 1);
}

int MutexlockLock(mutexlock_t *mutexlock, uint32_t mode);
void MutexlockUnlock(mutexlock_t *mutexlock);
#endif